package loader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;





/**
 * @说明 需要使用的函数只有getfromfile（传入文件名包括包名）和getfromstr（传入字符串，一定要是json格式的字符串），会返回一个jsonvalue，判断其为map，array或者其他然后调用里面的方法（java自己的，没有重写）即可得到结果，int，string等的方法详见JSONValue
 * @author 黄锐恒
 *
 */


public class JSONParse {
	
/**
 * @说明 该函数用于从名字为name的文件里读取字符串并解析并返回解析结果
 * @param name(记得加包名)
 * @return 一个JSONValue（json的基本类型）（为Object对象时为hashmap）
 * @throws ParseException
 * @throws IOException 
 */
	
	public static JSONValue getfromfile(String name) throws ParseException, IOException{
		return JSONParse.parse(read(name));
	}
	
	/**
	 * @说明 该函数用于解析str并返回解析结果
	 * @param name
	 * @return 一个JSONValue（json的基本类型）（为Object对象时为hashmap）
	 * @throws ParseException
	 */
	public static JSONValue getfromstr(String str) throws ParseException{
		return JSONParse.parse(str);
	}
	
	
	
	/**
	 * @说明 传入文件名即可读取并输出文件里的字符串
	 * @author 黄锐恒
	 * @注意 文件名可能需要加包名，变量rname为文件名全称
	 * @param name
	 * @return 文件里的字符串
	 * @throws IOException 
	 */
	
	
	private static String read(String name) throws IOException {
		String jname = name;
		String rname =  name + ".json";
		
		System.out.println(rname);
		
		ClassLoader classLoader = JSONParse.class.getClassLoader();
		InputStream io = classLoader.getResourceAsStream(rname);
		
		if(io ==null) {
			System.out.println("配置文件读取异常,请重新安装");
			
		}
		String text = readFromInputStream(io);
		System.out.println(text);
		return text;
	}





/**
 * @author 黄锐恒
 * @说明 从io里读取并返回字符串
 * @param io
 * @return
 * @throws IOException 
 */
	private static String readFromInputStream(InputStream io) throws IOException {
        StringBuilder resultStringBuilder = new StringBuilder();
        try (BufferedReader br
                     = new BufferedReader(new InputStreamReader(io))) {
            String line;
            while ((line = br.readLine()) != null) {
                resultStringBuilder.append(line).append("\n");
            }
        }
        return resultStringBuilder.toString();
	}










	/**
	 * @author 黄锐恒
	 * @说明 调用内部类Parser的parseValue方法，需要给内部类传入字符串，得到解析后的结果
	 * @param jsonStr
	 * @return JSONValue
	 * @throws ParseException
	 */
	public static JSONValue parse(String jsonStr) throws ParseException{
			return new Parser(jsonStr).parseValue();
	}
	
	

	static class Parser{
		char[] charArray;//逐个字符解析
		int curr;//下标记录位置
		//传入要解析的字符串，生成字符数组进行解析
		/**
		 * Parser构造函数
		 * @param jsonStr
		 */
		public Parser(String jsonStr){
			this.charArray = jsonStr.toCharArray();
			this.curr = 0;
		}
		
		
		
		/**
		 * @author 黄锐恒
		 * @说明 核心解析方法，用于调用其他的解析方法
		 *
		 * @return JSONValue
		 * @throws ParseException
		 */
		//总调用的方法
		public JSONValue parseValue() throws ParseException{
			while(curr<charArray.length){
				//是否为空与是是否为换行
				if(charArray[curr]<=' '){
					curr++;
					continue;
				}
				//对非空的字符进行判断(这里没写t，f，n)
				switch(charArray[curr]){
				case '{' : {
					return parseObject();//解析object
				}
				case '[' : {
					return parseArray();//解析array
				}
				case '\'' :
				case '"'  :{
					return parseString();//解析string
				}
				//把true，false进行解析，返回 bool()
				case 't' :{
					return parseTure();
				}
				case 'f' :{
					return parseFalse();
				}
				case 'n' :{
					return parseNull();
				}
				default:{
					if(charArray[curr] <= '9' && charArray[curr] >= '0'){
						return parseNumber();//解析数字
					}
					throw new ParseException("unexepect char" + charArray[curr] , curr);//报错
				}
				
			}
		}
			return null;
	}
		
		
		
		
		
		
/**
 * 下面的方法不作介绍，反正就是各JSON数据类型的解析方法
 * @author 黄锐恒
 * @return
 * @throws ParseException
 */
		
		
		
		





		//处理对象，遇到}才退出该函数
		private JSONObject parseObject() throws ParseException {
			JSONObject object = new JSONObject();
			curr++;
			while(this.curr < this.charArray.length - 1){
				//把前面的空格去掉
				while (charArray[curr] <= ' '){
					curr++;
				}
				//必然是字符串（key）：value的格式，因此直接先解析第一个字符串作为key
				String key = parseString().get();
				//去掉冒号前的空格
				while (charArray[curr] != ':'){
					
					curr++;
				}
				//去掉冒号
				curr++;
				//去掉冒号后的空格
				while (charArray[curr] <= ' '){
					curr++;
				}
				//冒号后面要进行总调用
				JSONValue value = parseValue();
				//填充jsonobj
				object.put(key, value);
				//跳逗号/分号前的空格
				while(charArray[curr] <= ' '){
					curr++;
				}
				//分号跳出循环
				if(charArray[curr] == '}'){
					curr++;
					break;
				}
				//逗号继续循坏
				else if(charArray[curr] == ','){
					curr++;
				}
				else{
					throw new ParseException("except '}' or ',' found" + charArray[curr],curr);
				}
			}
			return object;
		}
		
		
		
		//处理数字，返回一个浮点数或者整数
		private JSONValue parseNumber() throws ParseException {
			StringBuilder builder = new StringBuilder();
			while(charArray[curr] == '.' || (charArray[curr] >= '0' && charArray[curr] <= '9')){
				builder.append(charArray[curr]);//字符append到bulider最后
				
				curr++;	
			}
			String str = builder.toString();
			
			if(str.contains(".")){
				return new JSONFloat(java.lang.Float.parseFloat(str));
			}
			//System.out.println(new JSONInt(Integer.parseInt(str)));
			return new JSONInt(Integer.parseInt(str));
		}
		
		
		
		//处理字符串，直到右边有相同符号才停止处理
		private JSONString parseString() throws ParseException {
			StringBuilder builder = new StringBuilder();
			if(charArray[curr] == '\''){
				curr++;
				while(charArray[curr] != '\''){
					builder.append(charArray[curr]);//字符append到bulider最后
					curr++;
				}
			}
			else if(charArray[curr] == '"'){
				
				curr++;
				while(charArray[curr] != '"' && curr<charArray.length){
					builder.append(charArray[curr]);
					curr++;
				}
			}
			else{
				throw new ParseException("unexepect char" + charArray[curr] , curr);
				
			}
			curr++;
			
			return new JSONString(builder.toString());
			
		}
		
		
		
		private JSONArray parseArray() throws ParseException {
			curr++;
			JSONArray array = new JSONArray();
			while(this.curr < this.charArray.length - 1){
				//把前面的空格去掉
				while (charArray[curr] <= ' '){
					curr++;
				}
				//去掉空格后中间一定是value
				array.add(parseValue());
				//去掉后的空格
				while (charArray[curr] <= ' '){
					curr++;
				}
				if(charArray[curr] == ']'){
					curr++;
					break;
				}else if(charArray[curr] == ','){
					curr++;
				}else{
					throw new ParseException("expect '] or ',' in fact found " + charArray[curr] , curr);
				}
			}
			return array;
		}
		
		
		//若为null，返回一个空值null
		private JSONValue parseNull() {
			if(charArray[++curr] != 'u' ||
					charArray[++curr] != 'l'||
					charArray[++curr] != 'l'
					){
				try {
					throw new ParseException("except token 'null'", curr);
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
			curr++;
			return null;
		}



		//判断是否为flase，有f但不是false就报错
		private JSONBool parseFalse() {
			if(charArray[++curr] != 'a' ||
					charArray[++curr] != 'l'||
					charArray[++curr] != 's'||
					charArray[++curr] != 'e'
					){
				try {
					throw new ParseException("except token 'false'", curr);
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
			curr++;
			return new JSONBool(false);
		}



//判断是否为true，有t但不是true就报错
		private JSONBool parseTure() {
			if(charArray[++curr] != 'r' ||
					charArray[++curr] != 'u'||
					charArray[++curr] != 'e'
					){
				try {
					throw new ParseException("except token 'true'", curr);
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
			curr++;
			return new JSONBool(true);
		}

	
		}
}
